package com.quotes.simulation;

import java.util.*;
import org.apache.log4j.Logger;

import com.quotes.Parameters;
import com.quotes.datamodell.*;
import com.quotes.dates.TimeRange;
import com.quotes.indicators.*;

public class AlgorithmicTrader
{
	private Logger logger = Logger.getLogger(getClass().toString());
	private Portfolio portfolio = null;
	private QuotesList quotesList = null;
	private TimeRange range = null;
	private Parameters parameters = null;
	
	public AlgorithmicTrader(QuotesList quotesList, TimeRange range, Parameters parameters) {
		this.portfolio = new Portfolio(quotesList, parameters);
		this.quotesList = quotesList;
		this.range = range;
		this.parameters = parameters;
	}
	
	public Portfolio getPortfolio() {
		return portfolio;
	}
	
	public MarketOrderList getMarketOrders(QuotesList products) {
		MarketOrderList orders = new MarketOrderList();
		
		for (Quotes quotes : quotesList.getQuotes()) {
			MarketOrderList list = getMarketOrders(quotes);
			orders.add(list);
		}

		return orders;
	}

	public MarketOrderList getMarketOrders(Quotes quotes) {
		TimeSeries closePrices = quotes.getQuote(QuotesType.CLOSE);
		Date[] dates = closePrices.extract(range).DatesAsArray();

		int[] macdTicks = parameters.getAsIntArray("macd.ticks");
		MacdIndicator macdIndicator = new MacdIndicator(quotes, macdTicks[0], macdTicks[1], macdTicks[2]);
//		TimeSeries macd macdIndicator.getMacdHistogramm().filterZeroCrossings()
		
		int[] coppockTicks = parameters.getAsIntArray("coppock.ticks");
		CoppockIndicator coppockIndicator = new CoppockIndicator(quotes, coppockTicks[0], coppockTicks[1], coppockTicks[2]);
		TimeSeries coppock = coppockIndicator.getCoppoc();
		TimeSeries coppockCrossings = coppock.filterZeroCrossings();
		
		MomentumIndicator momentumIndicator = new MomentumIndicator(quotes, 14);
    	TimeSeries momentum = momentumIndicator.getMomentum();
    	
		int adxTicks = parameters.getAsInt("adx.ticks");
		AdxIndicator adxIndicator = new AdxIndicator(quotes, adxTicks);
		TimeSeries adx = adxIndicator.getAdx();
    	TimeSeries diPlus = adxIndicator.getDiPlus();
    	TimeSeries diMinus = adxIndicator.getDiMinus();
		
		int rsiTicks = parameters.getAsInt("rsi.ticks");
    	RsiIndicator rsiIndicator = new RsiIndicator(quotes, rsiTicks);
    	TimeSeries rsi = rsiIndicator.getRsi();
    	
    	MarketOrderList marketOrders = new MarketOrderList();
    	
    	for (int i=1; i<dates.length; i++) {
    		Date today = dates[i];
    		double adxToday = adx.getOr0(today);
    		double rsiToday = rsi.getOr0(today);
    		double diPlusToday = diPlus.getOr0(today);
    		double diMinusToday = diMinus.getOr0(today);
    		double momentumToday = momentum.getOr0(today);
    		
    		MarketOrder order = null;
    		
    		if (coppockCrossings.getOr0(today) == 1) {
    			order = new MarketOrder(quotes.getSymbol(), today, BuySell.BUY);
    		} else if (coppockCrossings.getOr0(today) == -1) {
    			order = new MarketOrder(quotes.getSymbol(), today, BuySell.SELL);
    		}
    		   		
    		if (order != null && adxToday > 20) {
    			order.addInfo("rsi", rsiToday);
    			order.addInfo("adx", adxToday);
    			order.addInfo("diplus", diPlusToday);
    			order.addInfo("diminus", diMinusToday);
    			order.addInfo("momentum", momentumToday);
    			marketOrders.add(order);
    		}
    	}

    	return marketOrders;
	}
	
	public SimulationResult trade() {
		MarketOrderList marketOrders = getMarketOrders(quotesList);
		
		TimeSeries value = new TimeSeries(quotesList.get(0).getQuote(QuotesType.CLOSE).extract(range).DatesAsArray());
		
		Date[] dates = value.DatesAsArray();
		for (int i=0; i<dates.length; i++) {
			Date today = dates[i];
			MarketOrderList todaysMarketOrders = marketOrders.byDate(today);
			MarketOrderList buys = todaysMarketOrders.byDirection(BuySell.BUY);
			MarketOrderList sells = todaysMarketOrders.byDirection(BuySell.SELL);
			
			portfolio.setTradingDate(today);
			for (MarketOrder order : buys.getMarketOrders()) {
				portfolio.buy(order);
			}
			
			for (MarketOrder order : sells.getMarketOrders()) {
				portfolio.sell(order);
			}
		}
		
		return portfolio.getResult();
	}
}
